package middleware

import (
	"encoding/json"
	"fmt"
	"gitee.com/wuzheng0709/backend-gopkg/infrastructure/config"
	"gitee.com/wuzheng0709/backend-gopkg/infrastructure/connector/redis"
	"gitee.com/wuzheng0709/backend-gopkg/infrastructure/pkg/code"
	"gitee.com/wuzheng0709/backend-gopkg/infrastructure/pkg/gin/log"
	"gitee.com/wuzheng0709/backend-gopkg/infrastructure/pkg/httpclient"
	"gitee.com/wuzheng0709/backend-gopkg/infrastructure/pkg/jwt"
	"gitee.com/wuzheng0709/backend-gopkg/infrastructure/pkg/util"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)

const ecmTokenPre = "ecm_token_"

// Ecm云文档接口检查，获取登录token
func EcmTokenAuth(skipper ...SkipperFunc) gin.HandlerFunc {
	return func(c *gin.Context) {
		if len(skipper) > 0 && skipper[0](c) {
			c.Next()
			return
		}
		token := c.Request.Header.Get("token")
		if token == "" {
			c.JSON(400, gin.H{
				"code": code.Token_Error,
				"msg":  "请求未携带token,无权限访问",
			})
			c.Abort()
			return
		}
		log.Info("get token: ", token)

		claims, err := jwt.ParseTokenFromRedis(token)
		log.Info("get uid: ", claims.UserId)
		if err != nil || claims.UserId == "" {
			c.JSON(400, gin.H{
				"code": code.Token_Error,
				"msg":  "token 失效",
			})
			c.Abort()
			return
		}

		ecmToken := c.Request.Header.Get("ecmToken")
		if ecmToken == "integration" {
			//根据系统token,实现与ecm联动，获取集成登录token
			//token, err = GetEcmUserLoginIntegrationByUserLoginName(claims.UserId)
			token, err = GetEcmUserLoginIntegrationByUserLoginNameV(c)
			if err != nil {
				c.JSON(400, gin.H{
					"code": code.Token_Error,
					"msg":  err.Error(),
				})
				c.Abort()
				return
			}
		} else if ecmToken == "permanent" {
			if config.C.ECM.PermanentToken == "" {
				c.JSON(400, gin.H{
					"code": code.Token_Error,
					"msg":  "获取永久Token错误",
				})
				c.Abort()
				return
			}
			token = config.C.ECM.PermanentToken
		}
		// 替换token
		c.Set("token", token)
	}
}

func GetEcmUserLoginIntegrationByUserLoginNameV(c *gin.Context) (string, error) {
	return GetEcmUserLoginIntegrationByUserLoginNameV1(c, config.C.ECM.UrlHost, config.C.ECM.IntergrationKey)
}

/*
GetEcmToken

	TODO： 获取 token，存在漏洞，当token在接口调试的过程中，通过接口获取token一定会被替换掉，则toke无法使用；
	1、需要手动删除redis 中的token缓存才能生效
	⚠️：正式环境上线后，不允许手动调用token接口进行调试， 除非添加 token 校验策略: 用于判断token的有效性；
*/
func GetEcmUserLoginIntegrationByUserLoginNameV1(c *gin.Context, urlHost, secretKey string) (string, error) {
	loginName := c.GetString("ecmAccount")
	//loginName = strings.ToLower(loginName)
	redisPre := ecmTokenPre + loginName
	// 1、 从 reids 缓存中获取 token

	redisToken := redis.ImRedisDB.Get(redisPre).Val()
	if redisToken != "" {
		return redisToken, nil
	} else {
		// 2、 无法取到toke，直接调用接口生成新的
		ecmUrl := fmt.Sprintf("%s/api/services/Org/UserLoginIntegrationByUserLoginName", urlHost)
		body := map[string]interface{}{}
		body["loginName"] = loginName
		body["ipAddress"] = GetRealIp(c)
		body["integrationKey"] = secretKey
		bodyByte, err := json.Marshal(body)
		if err != nil {
			return "", err
		}
		header := http.Header{}
		header.Set("Accept", "application/json")
		header.Set("Content-Type", "application/json")
		resBody, _, err := httpclient.PublicRequireByPost(ecmUrl, header, bodyByte)
		if err != nil {
			return "", err
		}
		log.Info("JWT ******", ecmUrl, "\nHeader: ", header, "\nReqest: ", string(bodyByte), "\nRespbody:", string(resBody), "\nerr:", err, "\n")

		var resp map[string]interface{}
		if err = json.Unmarshal(resBody, &resp); err != nil {
			return "", err
		}

		if token, ok := resp["data"]; !ok || token == nil {
			printStr := fmt.Sprintf("ecmUrl:%s;\nHeader:%s;\nReqest:%s;\nRespbody:%s", ecmUrl, header, string(bodyByte), string(resBody))
			return "", fmt.Errorf("未查询到Token。%s", printStr)
		} else {
			if statusCmd := redis.ImRedisDB.
				Set(redisPre, token, time.Duration(util.Get24Time(time.Now()).Unix()-time.Now().Unix())*time.Second); statusCmd.Err() != nil {
				log.Error("ecm token 写入 redis 失败，err:", err.Error())
			}
			return fmt.Sprintf("%s", token), nil
		}
	}
}
